package com.xtedu.examproject.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xtedu.examproject.entity.Menu;
import com.xtedu.examproject.entity.MenuPath;
import com.xtedu.examproject.entity.Role;
import com.xtedu.examproject.entity.User;
import com.xtedu.examproject.service.MenuPathService;
import com.xtedu.examproject.service.MenuService;
import com.xtedu.examproject.service.RoleService;
import com.xtedu.examproject.util.MenuTreeBuilder;
import com.xtedu.examproject.util.NavManagementUtil;
import com.xtedu.examproject.util.PageHelper;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("/maintainnavigation/*")//菜单管理
public class NavigationServlet extends HttpServlet {
    private static final Logger log = LoggerFactory.getLogger(NavigationServlet.class);
    private MenuService menuService;
    private MenuPathService menuPathService;
    private NavManagementUtil navManagementUtil;
    private RoleService roleService;
    private PageHelper page;

    public void init() {
        menuService = new MenuService();
        menuPathService = new MenuPathService();
        navManagementUtil = new NavManagementUtil();
        roleService = new RoleService();
    }

    /**
     * 提取URL中的action参数（纯工具方法，不执行业务逻辑）
     */
    private String extractActionFromRequest(HttpServletRequest request) {
        String action = null;
        String pathInfo = request.getPathInfo();

        if (pathInfo != null && pathInfo.length() > 1) {
            action = pathInfo.substring(1);
        } else {
            String uri = request.getRequestURI();
            String contextPath = request.getContextPath();
            String path = uri.substring(contextPath.length());

            int lastSlashIndex = path.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < path.length() - 1) {
                action = path.substring(lastSlashIndex + 1);
            }
        }
        return action;
    }

    /**
     * 路由GET请求到相应的显示方法
     */
    private void routeGetRequest(String action, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        switch (action) {
            case "shownavigation":
                handleShowNavigationGet(request, response); // 显示导航页面
                break;
            case "addnavigation":
                handleAddNavigationGet(request, response); // 显示添加表单
                break;
            case "updatenavigation":
                handleEditNavigationGet(request, response); // 显示编辑表单
                break;
            case "delnavigation":
                handleDeleteNavigationGet(request, response); // 显示删除表单
                break;
            default:
                // 默认显示主页
                handleDeleteNavigationGet(request, response); // 显示删除表单
                break;
        }
    }

    /**
     * 路由POST请求到相应的处理方法
     */
    private void routePostRequest(String action, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        switch (action) {
            case "addnavigation":
                handleAddNavigationPost(request, response);// 处理添加表单提交
                break;
            case "updatenavigation":
                handleEditNavigationPost(request, response);
                break;
            case "delnavigation":
                handleDeleteNavigationPost(request, response);
                break;
            default:
                handleDeleteNavigationPost(request, response);
                break;
        }
    }

    private void handleAddNavigationGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/views/addnavigation.jsp").forward(request, response);
        // 可以重定向到POST方法或者返回错误
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("success", false);
        errorResponse.put("message", "请使用POST方法访问");

        ObjectMapper om = new ObjectMapper();
        response.getWriter().write(om.writeValueAsString(errorResponse));
    }

    private void handleAddNavigationPost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 设置统一的响应类型
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        ObjectMapper om = new ObjectMapper();
        Map<String, Object> responseData = new HashMap<>();

        try {
            // 首先检查是否是表单提交（有请求体内容）
            boolean isFormSubmission = false;
            StringBuilder requestBody = new StringBuilder();
            BufferedReader reader = request.getReader();

            String line;
            while ((line = reader.readLine()) != null) {
                requestBody.append(line);
                isFormSubmission = true;
            }

            if (isFormSubmission) {
                // ==================== 处理前端表单提交 ====================
                log.info("接收到前端表单提交数据: {}", requestBody);

                // 解析JSON数据
                String jsonData = requestBody.toString();
                Map<String, Object> formData = om.readValue(jsonData, Map.class);

                // 提取表单字段 - 添加类型转换和空值检查
                String navName = getStringValue(formData, "navName");
                Object navLinkObj = formData.get("navLink");
                Object parentNavObj = formData.get("parentNav");
                String navIcon = getStringValue(formData, "navIcon");
                Object roleIdObj = formData.get("roleId");
                Object navLinkPathObj = formData.get("navLinkPath");

                // 记录接收到的数据
                log.info("表单数据 - 导航名称: {}", navName);
                log.info("表单数据 - 导航链接: {}", navLinkObj);
                log.info("表单数据 - 父级导航: {}", parentNavObj);
                log.info("表单数据 - 导航图标: {}", navIcon);
                log.info("表单数据 - 角色ID: {}", roleIdObj);
                log.info("表单数据 - 链接路径: {}", navLinkPathObj);

                // 数据验证
                if (navName == null || navName.trim().isEmpty()) {
                    responseData.put("success", false);
                    responseData.put("message", "导航名称不能为空");
                    out.write(om.writeValueAsString(responseData));
                    return;
                }

                if (navLinkObj == null) {
                    responseData.put("success", false);
                    responseData.put("message", "请选择导航链接");
                    out.write(om.writeValueAsString(responseData));
                    return;
                }

                // 转换参数类型，处理可能的类型不匹配
                int navLink;
                int parentNav;
                int roleId;
                String navLinkPath;
                // 在参数转换部分增加更详细的错误信息
                try {
                    navLink = Integer.parseInt(navLinkObj.toString());
                    parentNav = parentNavObj != null ? Integer.parseInt(parentNavObj.toString()) : 0;
                    roleId = Integer.parseInt(roleIdObj.toString());
                    navLinkPath = navLinkPathObj.toString();

                    log.info("参数转换成功 - navLink: {}, parentNav: {}, roleId: {}, navLinkPath: {}",
                            navLink, parentNav, roleId, navLinkPath);

                } catch (NumberFormatException | NullPointerException e) {
                    log.error("参数类型转换失败 - navLinkObj: {}, parentNavObj: {}, roleIdObj: {}, navLinkPathObj: {}",
                            navLinkObj, parentNavObj, roleIdObj, navLinkPathObj, e);

                    responseData.put("success", false);
                    responseData.put("message", "参数格式错误: " + e.getMessage());
                    out.write(om.writeValueAsString(responseData));
                    return;
                }
                /*int roleId, String menuName, int menuId, String menuPath, String menuIcon, int menuParentId
                 * */
                // 调用Service层处理业务逻辑
                boolean success = navManagementUtil.addNewMenu(roleId, navName, navLink, navLinkPath, navIcon, parentNav);
                navManagementUtil.insertRoleMenu(roleId, navName, navLinkPath);
                navManagementUtil.updateSessionMenu(request);// 更新session中的菜单数据
                // 记录操作结果
                log.info("添加菜单操作结果: {}", success);

                // 结果处理
                if (success) {
                    responseData.put("success", true);
                    responseData.put("message", "导航添加成功");
                } else {
                    responseData.put("success", false);
                    responseData.put("message", "导航添加失败，请重试");
                }

                out.write(om.writeValueAsString(responseData));

            } else {
                // ==================== 发送数据给前端渲染页面 ====================
                log.info("向前端发送页面渲染数据");

                List<Menu> menus = menuService.findMenusByRoleId(3); // 获取用户3（管理员）的菜单
                List<MenuPath> menuPaths = menuPathService.findAll(); // 获取非管理员的菜单
                List<MenuPath> NavLink = navManagementUtil.getNavLink(menuPaths, menus);// 获取导航链接
                List<Role> roles = roleService.findAll();// 获取所有用户
                // 记录获取到的数据量
                log.info("获取到菜单数量: {}, 路径数量: {}, 角色数量: {}",
                        menus != null ? menus.size() : 0,
                        menuPaths != null ? menuPaths.size() : 0,
                        roles != null ? roles.size() : 0);

                // 创建包含多个数据的Map
                responseData.put("NavLink", NavLink);
                responseData.put("menus", menus);
                responseData.put("roles", roles);
                responseData.put("success", true);

                out.write(om.writeValueAsString(responseData));
            }

        } catch (Exception e) {
            // 错误处理
            log.error("菜单管理异常", e);

            responseData.put("success", false);
            responseData.put("message", "服务器错误: " + e.getMessage());

            try {
                out.write(om.writeValueAsString(responseData));
            } catch (Exception ex) {
                log.error("生成错误响应失败", ex);
                out.write("{\"success\": false, \"message\": \"系统错误\"}");
            }

            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    private void handleShowNavigationGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            User user = navManagementUtil.updateSessionMenu(request);
            List<Menu> menus = menuService.findMenusByRoleId(user.getRoleId());
            List<Menu> menuTree = MenuTreeBuilder.buildMenuTree(menus);
            request.setAttribute("menuTree", menuTree);
            user.setMenus(menuTree);
            request.getSession().setAttribute("user", user);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        request.getRequestDispatcher("/WEB-INF/views/shownavigation.jsp").forward(request, response);
    }

    private void handleShowNavigationPost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {

    }

    private void handleEditNavigationGet(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Menu oldMenu = menuService.findById(Integer.parseInt(request.getParameter("id")));
        Integer oldRoleId = navManagementUtil.getRoleMenuByMenuId(oldMenu.getId()).get(0);
        request.setAttribute("oldRoleId", oldRoleId);
        request.setAttribute("oldMenu", oldMenu);// 获取菜单信息
        request.getRequestDispatcher("/WEB-INF/views/updatenavigation.jsp").forward(request, response);
        // 可以重定向到POST方法或者返回错误
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("success", false);
        errorResponse.put("message", "请使用POST方法访问");

        ObjectMapper om = new ObjectMapper();
        response.getWriter().write(om.writeValueAsString(errorResponse));

    }

    private void handleEditNavigationPost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        // 设置统一的响应类型
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        ObjectMapper om = new ObjectMapper();
        Map<String, Object> responseData = new HashMap<>();

        try {
            // 首先检查是否是表单提交（有请求体内容）
            boolean isFormSubmission = false;
            StringBuilder requestBody = new StringBuilder();
            BufferedReader reader = request.getReader();

            String line;
            while ((line = reader.readLine()) != null) {
                requestBody.append(line);
                isFormSubmission = true;
            }

            if (isFormSubmission) {
                // ==================== 处理前端表单提交 ====================
                log.info("接收到前端表单提交数据: {}", requestBody);

                // 解析JSON数据
                String jsonData = requestBody.toString();
                Map<String, Object> formData = om.readValue(jsonData, Map.class);

                // 提取表单字段 - 添加类型转换和空值检查
                String navName = getStringValue(formData, "navName");
                Object navLinkObj = formData.get("navLink");
                Object parentNavObj = formData.get("parentNav");
                String navIcon = getStringValue(formData, "navIcon");
                Object roleIdObj = formData.get("roleId");
                Object navLinkPathObj = formData.get("navLinkPath");


                // 记录接收到的数据
                log.info("表单数据 - 导航名称: {}", navName);
                log.info("表单数据 - 导航链接: {}", navLinkObj);
                log.info("表单数据 - 父级导航: {}", parentNavObj);
                log.info("表单数据 - 导航图标: {}", navIcon);
                log.info("表单数据 - 角色ID: {}", roleIdObj);
                log.info("表单数据 - 链接路径: {}", navLinkPathObj);

                // 数据验证
                if (navName == null || navName.trim().isEmpty()) {
                    responseData.put("success", false);
                    responseData.put("message", "导航名称不能为空");
                    out.write(om.writeValueAsString(responseData));
                    return;
                }

                if (navLinkObj == null) {
                    responseData.put("success", false);
                    responseData.put("message", "请选择导航链接");
                    out.write(om.writeValueAsString(responseData));
                    return;
                }

                // 转换参数类型，处理可能的类型不匹配
                int navLink;
                int parentNav;
                int roleId;
                String navLinkPath;

                // 在参数转换部分增加更详细的错误信息
                try {
                    navLink = Integer.parseInt(navLinkObj.toString());
                    parentNav = parentNavObj != null ? Integer.parseInt(parentNavObj.toString()) : 0;
                    roleId = Integer.parseInt(roleIdObj.toString());
                    navLinkPath = navLinkPathObj.toString();

                    log.info("参数转换成功 - navLink: {}, parentNav: {}, roleId: {}, navLinkPath: {}",
                            navLink, parentNav, roleId, navLinkPath);

                } catch (NumberFormatException | NullPointerException e) {
                    log.error("参数类型转换失败 - navLinkObj: {}, parentNavObj: {}, roleIdObj: {}, navLinkPathObj: {}",
                            navLinkObj, parentNavObj, roleIdObj, navLinkPathObj, e);

                    responseData.put("success", false);
                    responseData.put("message", "参数格式错误: " + e.getMessage());
                    out.write(om.writeValueAsString(responseData));
                    return;
                }
                /*int roleId, String menuName, int menuId, String menuPath, String menuIcon, int menuParentId
                 * */
                // 调用Service层处理业务逻辑
//                boolean success = navManagementUtil.addNewMenu(roleId, navName, navLink, navLinkPath, navIcon, parentNav);
//                navManagementUtil.insertRoleMenu(roleId, navName, navLinkPath);
                //获得所需要修改的id
                int menuId = menuService.findIdByNameAndPath(navName, navLinkPath);
                Menu newMenu = new Menu();
                newMenu.setId(menuId);//设置id
                newMenu.setName(navName);//设置名称
                newMenu.setPath(navLinkPath);//设置路径
                newMenu.setIcon(navIcon);//设置图标
                newMenu.setPid(parentNav);//设置父级id
                newMenu.setState(true);//设置状态,默认显示
                //更新菜单
                boolean success = menuService.update(newMenu) > 0;

                navManagementUtil.updateSessionMenu(request);// 更新session中的菜单数据
                // 记录操作结果
                log.info("修改菜单操作结果: {}", success);

                // 结果处理
                if (success) {
                    responseData.put("success", true);
                    responseData.put("message", "导航修改成功");
                } else {
                    responseData.put("success", false);
                    responseData.put("message", "导航修改失败，请重试");
                }

                out.write(om.writeValueAsString(responseData));

            } else {
                // ==================== 发送数据给前端渲染页面 ====================
                log.info("向前端发送页面渲染数据");

                List<Menu> menus = menuService.findMenusByRoleId(3); // 获取用户3（管理员）的菜单
                List<MenuPath> menuPaths = menuPathService.findAll(); // 获取非管理员的菜单
                List<MenuPath> NavLink = navManagementUtil.getNavLink(menuPaths, menus);// 获取导航链接
                List<Role> roles = roleService.findAll();// 获取所有用户
                // 记录获取到的数据量
                log.info("获取到菜单数量: {}, 路径数量: {}, 角色数量: {}",
                        menus != null ? menus.size() : 0,
                        menuPaths != null ? menuPaths.size() : 0,
                        roles != null ? roles.size() : 0);

                // 创建包含多个数据的Map
                responseData.put("NavLink", NavLink);
                responseData.put("menus", menus);
                responseData.put("roles", roles);
                responseData.put("success", true);

                out.write(om.writeValueAsString(responseData));
            }

        } catch (Exception e) {
            // 错误处理
            log.error("菜单管理异常", e);

            responseData.put("success", false);
            responseData.put("message", "服务器错误: " + e.getMessage());

            try {
                out.write(om.writeValueAsString(responseData));
            } catch (Exception ex) {
                log.error("生成错误响应失败", ex);
                out.write("{\"success\": false, \"message\": \"系统错误\"}");
            }

            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }

    }

    private void handleDeleteNavigationGet(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        try {
            // 获取菜单数据并设置到request中
            List<Menu> menus = menuService.findAll();
            request.setAttribute("menuItems", menus);
            // 转发到JSP页面
            request.getRequestDispatcher("/WEB-INF/views/delnavigation.jsp").forward(request, response);
        } catch (Exception e) {
            request.setAttribute("errorMessage", "获取菜单数据失败: " + e.getMessage());
        }
    }

    private void handleDeleteNavigationPost(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();

        try {
            String idParam = request.getParameter("id");
            if (idParam != null && !idParam.trim().isEmpty()) {
                int id = Integer.parseInt(idParam.trim());// 获取菜单ID
                Menu menu = menuService.findById(id);// 根据ID查询菜单

                if (menu != null) {
                    boolean success = menuService.delete(menu) > 0 && navManagementUtil.delRoleMenu(id);
                    navManagementUtil.updateSessionMenu(request);// 更新session中的菜单数据
                    out.write("{\"success\": " + success + "}");
                } else {
                    out.write("{\"success\": false, \"message\": \"菜单不存在\"}");
                }
            } else {
                out.write("{\"success\": false, \"message\": \"缺少菜单ID参数\"}");
            }

        } catch (Exception e) {
            log("处理删除菜单请求时发生错误", e);
            out.write("{\"success\": false, \"message\": \"服务器错误\"}");
        }

    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //默认是get请求
        String action = extractActionFromRequest(request);
        try {
            routeGetRequest(action, request, response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String action = extractActionFromRequest(request);
        try {
            routePostRequest(action, request, response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 辅助方法：安全获取字符串值
    private String getStringValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? value.toString() : null;
    }
}